package nmf;

import java.util.Random;

import org.ejml.ops.NormOps;
import org.ejml.ops.RandomMatrices;
import org.ejml.simple.SimpleMatrix;

public class CenterNearTheAverageNMFTool extends NMFTool {
   
   @Override
   public void initialize(final SimpleMatrix V, final SimpleMatrix W, final SimpleMatrix H, final int[] trainClass) {
      // Idea: Set all the entries to random numbers between 0 and 2x,
      // where x is such that if all entries in W and H are set to x, then
      // every entry in WH is equal to the average of V's elements.
      final Random rand = new Random();
      final double mean = V.elementSum() / V.getNumElements();
      final double x = Math.sqrt(mean * W.numCols());
      
      double variance = 0;
      for (int i = 0; i < V.numRows(); i++) {
         for (int j = 0; j < V.numCols(); j++) {
            variance += (V.get(i, j) - mean) * (V.get(i, j) - mean);
         }
      }
      
      variance /= V.getNumElements();
      
      final double stdDev = Math.sqrt(variance);
      RandomMatrices.setRandom(W.getMatrix(), x + stdDev, x + 2 * stdDev, rand);
      // W.set(.015);
      H.set(.015);
      
   }
   
   @Override
   public double cost(final SimpleMatrix V, final SimpleMatrix W, final SimpleMatrix H) {
      return NormOps.fastNormF(V.minus(W.mult(H)).getMatrix());
   }
   
   @Override
   public String costString() {
      return "Frobenius Cost";
   }
   
   @Override
   public String toString() {
      return "Erics NMF Tool";
   }
   
}
